package services

import (
	"errors"
	"fmt"
	"gorm.io/gorm"
	global2 "longmen/server/config/global"
	"longmen/server/internal/rpc/tencentim/chat"
	"longmen/server/pkg/common/helper/const"
	string2 "longmen/server/pkg/common/helper/string"
	time2 "longmen/server/pkg/common/helper/timehelper"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	cache2 "longmen/server/pkg/db/redis/cache"
	"time"

	"github.com/jinzhu/copier"
	"longmen/server/pkg/common/api_models"
)

// 开通订阅
func (s *Service) SubNoble(uid int, nobleID uint8, anchorID int) error {
	myNoble, _ := s.GetMyNoble(uid)
	if myNoble.Id > int(nobleID) && myNoble.From != 2 {
		return errors.New("只能开通比当前更高等级的贵族")
	}
	noble, err := db_main.GetNobleById(nobleID)
	if err != nil {
		return err
	}
	price := noble.Price
	if myNoble.Id == int(nobleID) && myNoble.From != 2 { // 续费价
		price = noble.RenewPrice
	}

	user, err := mysql.GetUserParam(map[string]interface{}{"id": uid})
	if err != nil {
		return errors.New("用户信息获取失败")
	}

	if user.Diamond < int(price) {
		return errors.New("您的余额不足")
	}

	nr := &models_main.NobleRecord{
		NobleId:    nobleID,
		Uid:        uint(uid),
		AnchorId:   uint(anchorID),
		From:       1,
		Expiration: time.Now().Unix() + 30*24*3600 - 1,
	}

	if myNoble.Id == int(nobleID) {
		// 同等级的将未过期的时间加上
		nr.Expiration = nr.Expiration + myNoble.Expiration*24*3600
	}

	//历史被覆盖未过期的相同等级的贵族
	myNobleHistory, _ := s.GetMyNobleByID(uid, int(nobleID))
	if myNobleHistory.Id == int(nobleID) && myNobleHistory.Id != myNoble.Id {
		nr.Expiration = nr.Expiration + myNobleHistory.Expiration*24*3600
	}

	tx := global2.GetX().Begin()

	// 开入开通记录
	err = db_main.InsertNobleRecordByTx(tx, nr)
	if err != nil {
		tx.Rollback()
		return errors.New("开通贵族失败,记录异常")
	}

	// 发放道具
	err = awardProps(tx, uid, noble)

	// 扣除克拉
	_, _, err = db_main.UpdateAmount(uid, -int(price), _const.CoinDiamond, _const.SUBCRIBLE_NOBLE)

	if err != nil {
		tx.Rollback()
		return err
	}

	chat.SetClientUserVip(uid, int(nobleID))
	profitLog := []*models_main.UserProfit{
		{
			Uid:         user.Id,     //获得人的id, 这里是领取人
			CoinCount:   -int(price), //鹰钻或金坷拉数量
			FUid:        0,           //赠送人的ID, 系统赠送
			ConsumeType: _const.SUBCRIBLE_NOBLE,
			Type:        _const.TYPE_CONSUME, //赚钱记录
			Content: fmt.Sprintf("%s 开通贵族 %s(%d天)",
				user.NickName,
				noble.Name,
				30,
			),
			Resid:      0,
			Count:      0,
			CreateTime: time.Now(),
			CoinType:   int(_const.CoinDiamond), //1-鹰钻 2-金坷拉
			OrderNo:    util.GenOrderId("RV", 1),
			Liveid:     int64(anchorID),
		},
	}
	if err = db_main.InsertUserProfitByTransactions(tx, profitLog); err != nil {
		global2.Log.Error("%s开通贵族消费记录写入失败:%v", "SubNoble", profitLog)
	}

	cache2.PushFundFlow(user.Id, -int(price), _const.CoinDiamond, _const.SUBCRIBLE_NOBLE)

	tx.Commit()
	//删除用户缓存, 刷新龙钻数据
	cache2.DelUserFullCache(user.Id)
	if anchorID > 0 {
		db_main.SetUserRecommendNobleInc(int64(user.Id), int64(anchorID))
	}
	return nil
}

func (s *Service) GetMyNoble(uid int) (*api_models.GetNobleByIdResp, error) {
	record, err := db_main.GetNobleRecordByUid(uid)
	if err != nil {
		return nil, err
	}
	resp := &api_models.GetNobleByIdResp{}
	if record.Id > 0 {
		resp.Expiration = int64(time2.GetLeftDays(record.Expiration))
		nobleInfo, err := cache2.GetNoble(uint8(record.NobleId))

		if err != nil {
			return resp, err
		}
		resp.From = record.From
		resp.AnchorID = int64(record.AnchorId)
		err = copier.Copy(resp, nobleInfo)
		if err != nil {
			return nil, err
		}
	}
	return resp, nil
}

func (s *Service) GetMyNobleByID(uid int, nobleID int) (*api_models.GetNobleByIdResp, error) {
	record, err := db_main.GetNobleRecordByUidAndNobleID(uid, nobleID)
	if err != nil {
		return nil, err
	}
	resp := &api_models.GetNobleByIdResp{}
	if record.Id > 0 {
		resp.Expiration = int64(time2.GetLeftDays(record.Expiration))
		nobleInfo, err := cache2.GetNoble(uint8(record.NobleId))

		if err != nil {
			return resp, err
		}
		resp.From = record.From
		err = copier.Copy(resp, nobleInfo)
		if err != nil {
			return nil, err
		}
	}
	return resp, nil
}

func (s *Service) GetNobleById(id uint8) (*api_models.GetNobleByIdResp, error) {
	nobleInfo, err := cache2.GetNoble(id)
	if err != nil {
		return nil, err
	}
	resp := &api_models.GetNobleByIdResp{}
	resp.Expiration = 0
	err = copier.Copy(resp, nobleInfo)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (s *Service) GetNobleNameList() ([]*api_models.GetNobleListResp, error) {
	fName := "GetNobleNameList"
	nobleList, err := db_main.GetNobleNameList()
	if err != nil {
		err = fmt.Errorf("%s%s", util.Convert(fName), err.Error())
		return nil, err
	}
	return nobleList, nil
}

// 注册送的贵族盲盒
func (s *Service) ReceiveNoble(user *models_main.User) (*api_models.ReceiveNobleResp, error) {
	var (
		err     error
		vipLen  = 0
		fName   = "ReceiveNoble"
		vipDays = 5 //领取的VIP有效期5天
		expTime = time.Now().Unix() + 5*24*3600
		noble   *models_main.NobleNew
		// nobleRecord *api_models.NobleRecordRes
		nobleList []*models_main.NobleNew
		// userBackpack []*models.UserBackpack
		// profitLog    []*models.UserProfit
		from = 2
	)

	// 0.如果用户已经是VIP，且未到期不能领取
	// if nobleRecord, err = repository.GetNobleRecordByUid(user.Id); err != nil {
	// 	return nil, fmt.Errorf("%s %s", common.Convert(fName), err.Error())
	// }

	myNoble, _ := s.GetMyNoble(user.Id)

	// 1.获取等级列表
	nobleList, err = db_main.GetNobleList() // TODO 加缓存
	if vipLen = len(nobleList); err != nil {
		return nil, fmt.Errorf("%s %s", util.Convert(fName), err.Error())
	}
	if vipLen == 0 {
		return nil, errors.New("系统未配置VIP等级")
	}

	// 2.随机取一个VIP
	idx := string2.RandInt(0, vipLen)
	noble = nobleList[idx]
	if myNoble.Id > 0 {
		expTime = myNoble.Expiration*24*3600 + expTime
		noble, _ = db_main.GetNobleById(uint8(myNoble.Id))
		from = 1
	}
	// noblePrivilege, err := repository.GetNoblePrivilege(noble.Id)
	if err != nil {
		return nil, errors.New("系统未配置VIP等级信息")
	}

	tx := global2.GetX().Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	//发放道具
	err = awardProps(tx, user.Id, noble)
	if err != nil {
		return nil, err
	}

	// 写入一条等级关联记录
	if err = db_main.InsertNobleRecordByTx(tx, &models_main.NobleRecord{
		NobleId:    noble.Id,      //贵族ID
		Uid:        uint(user.Id), //用户ID
		Expiration: expTime,       //到期时间戳
		AnchorId:   uint(myNoble.AnchorID),
		From:       from,
		CreateTime: time2.GetTimeStamp(1),
	}); err != nil {
		return nil, fmt.Errorf("%s %s", util.Convert(fName), err.Error())
	}

	user.ReceiveVip = 1
	if err = db_main.UpdateUserByTransactions(tx, []string{"receive_vip"}, user); err != nil {
		return nil, fmt.Errorf("%s %s", util.Convert(fName), err.Error())
	}

	// if decimal.Reward > 0 {
	// 	// 7.写入账变记录
	// 	profitLog = []*models.UserProfit{
	// 		{
	// 			Uid:         user.Id,             //获得人的id, 这里是领取人
	// 			CoinCount:   int(decimal.Reward), //鹰钻或金坷拉数量
	// 			FUid:        0,                   //赠送人的ID, 系统赠送
	// 			ConsumeType: util.PROFIT_RECEIVE_NOBLE,
	// 			Type:        util.TYPE_PROFIT, //赚钱记录
	// 			Content: fmt.Sprintf("%s 领取VIP %s(%d天)，获得收益:%d克拉",
	// 				user.NickName,
	// 				noble.Name, vipDays,
	// 				decimal.Reward/100, //注意这里要除以100
	// 			),
	// 			Resid:      0,
	// 			Count:      0,
	// 			CreateTime: timehelper.Now(),
	// 			CoinType:   int(util.CoinDiamond), //1-鹰钻 2-金坷拉
	// 			OrderNo:    util.GenOrderId("RV", 1),
	// 			Liveid:     0,
	// 		},
	// 	}
	// 	global.Log.Debugf("%s写收益记录来源方:%v", fName, profitLog)

	// 	if err = repository.InsertUserProfitByTransactions(tx, profitLog); err != nil {
	// 		global.Log.Error("%s领取VIP获取收益记录写入失败:%v", fName, profitLog)
	// 	}

	// 8.写入消息通知
	// if err = repository.InsertNoticeByTx(tx, &models.Notice{
	// 	SenderUid:  uint(user.Id),
	// 	Content: fmt.Sprintf("恭喜您领取VIP %s：开盲盒，奖励如下：钻石x%d", noble.Name, decimal.Reward/100),
	// }); err != nil {
	// 	return nil, fmt.Errorf("%s %s", common.Convert(fName), err.Error())
	// }
	// }

	if err = tx.Commit().Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	cache2.DelUserFullCache(user.Id)

	return &api_models.ReceiveNobleResp{
		VipDay:  uint8(vipDays),
		VipName: noble.Name, //noble.Name
		RankId:  noble.Id,
		//NobleTitle: noblePrivilege.MountTitle,
	}, nil

}

// 发送道具
func awardProps(tx *gorm.DB, uid int, noble *models_main.NobleNew) error {
	// 发放道具
	var it api_models.NobleItems
	err := util.Json2Struct(noble.Trumpet, &it)
	if err != nil {
		tx.Rollback()
		return errors.New("获取贵族道具失败" + err.Error())
	} // 喇叭
	if it.PropsID > 0 {
		err = db_main.SaveUserItem(tx, int(noble.Id), uid, it.PropsID, it.Type, it.Amount, it.Name, it.Remark, 3000*24*60*60) // 不限时道具直接写入3000天
		if err != nil {
			tx.Rollback()
			return err
		}
	}

	var ib []api_models.NobleItems // 弹幕
	err = util.Json2Struct(noble.Barrage, &ib)
	if err != nil {
		tx.Rollback()
		return errors.New("获取贵族道具失败:" + err.Error())
	}

	for _, v := range ib {
		err = db_main.SaveUserItem(tx, int(noble.Id), uid, v.PropsID, v.Type, v.Amount, v.Name, v.Remark, 3000*24*60*60) // 不限时道具直接写入3000天
		if err != nil {
			tx.Rollback()
			return err
		}
	}
	// 坐骑
	mount, err := db_main.GetPropsINFO(int(noble.PropsID))
	if err != nil {
		tx.Rollback()
		return errors.New("获取贵族座骑信息失败")
	}
	err = db_main.SaveUserItem(tx, int(noble.Id), uid, mount.Id, mount.Type, 1, mount.Name, mount.Remark, 30*24*60*60)
	if err != nil {
		tx.Rollback()
		return err
	}
	chat.SetClientUserVip(uid, int(noble.Id))
	return nil
}
